Address sanitizer

> [!WARNING]
> This is not a good first issue to contribute. Great if you are interested to contribute to scikit-learn 🙏. Please have a look at our [contributing doc](https://scikit-learn.org/dev/developers/contributing.html) and in particular the section [Issues for new contributors](https://scikit-learn.org/dev/developers/contributing.html#new-contributors). 

### Describe the workflow you want to enable

This was discussed a little on issue https://github.com/scikit-learn/scikit-learn/issues/32491 and I wanted to give a bit of context about how to do it (unfortunately I don't think I know your CI workflow well enough to do it myself).

Essentially, address sanitizer is a compiler option which looks for out of bounds reads and writes so should catch errors like reading beyond the end of an array. It slows things down so you definitely don't want to distribute wheels with it enabled, but it may help with testing. It only works if you actually exercise the code so you'll want to build and run the tests. It's probably easiest to do on Linux and with just one Python version - there's likely little benefit to doing it comprehensively.

Undefined behaviour sanitizer is related and can be enabled at the same time. However it probably has less value, and there's some minor bits of undefined behaviour in Cython which you'll have to ignore.

### Describe your proposed solution

Rough outline:

* pick a compiler - `clang` is probably the best but `gcc` or `msvc` will work if you have strong preferences.
* Compile and link with `-fsanitize=address` as a command-line option.
* Run the tests with `ASAN_OPTIONS=detect_leaks=0` set as an environmental variable - Cython definitely doesn't clean everything up on exit so you'll get lots of fairly useless false positives.
* You may need `LD_PRELOAD=$(gcc --print-file-name=libasan.so)` as an environmental variable too.
* Dependency: I don't think it's strictly necessary to build all your dependencies with address sanitizer, however:
   * if you're linking to C++ libraries that use `std::string` and `std::vector` then it's a good idea to build them with it too (otherwise you have to manually disable some checks).
   * I imagine you're doing a lot of your memory allocation in Numpy? In which case it'd probably be a good idea to build Numpy with it too. I'm not the right person to advise on that.

Hopefully that makes some sense - feel ping me if it doesn't work, or close if it isn't something you want to do.


### Additional context

[Numpy doc](https://numpy.org/devdocs/dev/development_advanced_debugging.html#compiler-sanitizers) about compiler sanitizers

[Numpy CI workflow](https://github.com/numpy/numpy/blob/main/.github/workflows/compiler_sanitizers.yml)

COMMENT:
> [@Aymuos22](https://github.com/Aymuos22) this is not a good first issue to work on, great that you are interested to work on scikit-learn 🙏.
> 
> I would suggest you look at the GitHub's [How to contribute to Open-Source guide](https://opensource.guide/how-to-contribute/), which gives a good generic overview about how open-source works.
> 
> Please have a look at our [contributing doc](https://scikit-learn.org/dev/developers/contributing.html) and in particular the section [Issues for new contributors](https://scikit-learn.org/dev/developers/contributing.html#new-contributors).

Thanks for guiding a beginner

Labels: Build / CI